﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Ruleweaver.Rules
{
	internal sealed class ConvertRuleToString : RuleVisitor
	{
		private StringBuilder _builder;

		internal string ConvertToString(Rule rule)
		{
			_builder = new StringBuilder();

			Visit(rule);

			var ruleString = _builder.ToString();

			_builder = null;

			return ruleString;
		}

		protected override Rule VisitCheck(CheckRule checkRule)
		{
			_builder.Append(checkRule.Method.Name);

			if(checkRule.CheckArguments.Any())
			{
				_builder.Append("(");

				var wroteFirst = false;

				foreach(var extraArgument in checkRule.CheckArguments)
				{
					if(wroteFirst)
					{
						_builder.Append(", ");
					}
					else
					{
						wroteFirst = true;
					}

					_builder.Append(extraArgument);
				}

				_builder.Append(")");
			}

			return checkRule;
		}

		protected override Rule VisitFixed(FixedRule fixedRule)
		{
			_builder.Append(fixedRule.Passes.ToString());

			return fixedRule;
		}

		protected override Rule VisitComposite(CompositeRule compositeRule)
		{
			var first = true;

			foreach(var rule in compositeRule.Rules)
			{
				if(first)
				{
					first = false;

					_builder.Append("(");
				}
				else
				{
					_builder.Append(", ");
				}

				Visit(rule);
			}

			if(!first)
			{
				_builder.Append(")");
			}

			return compositeRule;
		}

		protected override Rule VisitField(MemberRule fieldRule)
		{
			_builder.AppendFormat(".{0} => ", fieldRule.Member.Name);

			Visit(fieldRule.Rule);

			return fieldRule;
		}

		protected override Rule VisitProperty(MemberRule propertyRule)
		{
			_builder.AppendFormat(".{0} => ", propertyRule.Member.Name);

			Visit(propertyRule.Rule);

			return propertyRule;
		}

		protected override Rule VisitMethod(MemberRule methodRule)
		{
			_builder.AppendFormat(".{0}() => ", methodRule.Member.Name);

			Visit(methodRule.Rule);

			return methodRule;
		}
	}
}